<template>
  <div>
    <!-- 菜单modal弹窗 -->
    <dtDialog
      :title="modalTitle"
      :visible.sync="dialogVisible"
      :lock-scroll="false"
      :append-to-body="true"
      :is-loading="loading"
      @closeDialog="onModalClosed"
      @comfirmBtn="onSubmit()"
    >
      <el-form ref="addMenuFormRef" slot="content" label-width="104px"
               :model="addMenuForm" :rules="rules">
        <el-row>
          <el-col :span="24">
            <el-form-item label="菜单名称" prop="menuName">
              <el-input v-model.trim="addMenuForm.menuName" maxlength="10" placeholder="请输入菜单名称"
                        show-word-limit class="limit" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="菜单编号" prop="menuCode" label-width="104px">
              <span slot="label">
                <span class="span-box">
                  <el-tooltip class="item" effect="dark" content="菜单编号需要与vue文件中组件name保持一致"
                              placement="top-start">
                    <i class="el-icon-question" />
                  </el-tooltip>
                  <span>菜单编号</span>
                </span>
              </span>
              <el-input v-model.trim="addMenuForm.menuCode" maxlength="50" placeholder="请输入菜单编号"
                        show-word-limit class="limit" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- <el-row>
          <el-col :span="24">
            <el-form-item label="页面名称" prop="menuCode" label-width="104px">
              <span slot="label">
                <span class="span-box">
                  <el-tooltip class="item" effect="dark" content="页面名称需要与vue文件中组件name保持一致" placement="top-start">
                    <i class="el-icon-question" />
                  </el-tooltip>
                  <span>页面名称</span>
                </span>
              </span>
              <el-input v-model.trim="addMenuForm.menuCode" maxlength="50" placeholder="请输入页面名称" show-word-limit class="limit" />
            </el-form-item>
          </el-col>
        </el-row> -->
        <el-row>
          <el-col :span="24">
            <el-form-item label="菜单类型" prop="menuType">
              <!-- <span slot="label">
                <span class="span-box">
                  <el-tooltip class="item" effect="dark" content="菜单类型中目录代表目录，菜单代表页面" placement="top-start">
                    <i class="el-icon-question" />
                  </el-tooltip>
                  <span> 菜单类型 </span>
                </span>
              </span> -->
              <el-radio v-model="addMenuForm.menuType" :label="'M'" @change="handleMenuType('M')">目录</el-radio>
              <el-radio v-model="addMenuForm.menuType" :label="'C'" @change="handleMenuType('C')">菜单</el-radio>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col>
            <el-form-item label="所属应用" prop="appCode">
              <el-radio v-for="(item,index) in sysAppList" :key="item.appCode" v-model.trim="addMenuForm.appCode"
                        :label="item.appCode" @change="appCodeChange(item,index)">{{ item.appName }}</el-radio>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="父级菜单" prop="menuParentName">
              <el-dialog
                :visible.sync="insideDialogVisible"
                :close-on-click-modal="false"
                append-to-body
                width="800px"
                title="父级菜单"
              >
                <!-- 搜索栏 -->
                <el-input
                  v-model.trim="filterText"
                  prefix-icon="el-icon-search"
                  placeholder="输入搜索组织名称"
                  maxlength="30"
                  style="margin: 20px 0;"
                />
                <el-tree
                  :ref="menuTree.ref"
                  :props="menuTree.props"
                  :data="menuTree.data"
                  node-key="nodeId"
                  :filter-node-method="filterNode"
                  check-strictly
                  highlight-current
                  :default-expanded-keys="menuTree.defaultExpandedKeys"
                />
                <span slot="footer" class="dialog-footer">
                  <el-button type="primary" @click="onSaveParentMenu">保存</el-button>
                  <el-button @click="insideDialogVisible = false">关闭</el-button>
                </span>
              </el-dialog>
              <el-input v-model.trim="addMenuForm.menuParentName" readonly placeholder="请选择父级菜单"
                        @focus="onFocusMenuPath" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="菜单图标" prop="antdvIcon" class="icon_class">
              <!-- 图标选择器 -->
              <IconPicker :icon="addMenuForm.antdvIcon" @change="handleSelectedIcon" />
              <i class="el-icon-delete" @click="addMenuForm.antdvIcon = ''" />
              <!-- <el-button class="selected-icon-button" type="small">删除图标</el-button> -->
            </el-form-item>
          </el-col>
        </el-row>

        <el-row>
          <el-col :span="24">
            <el-form-item label="排序" prop="menuSort">
              <el-input v-model.trim="addMenuForm.menuSort" placeholder="请输入排序" :oninput="initPositiveInteger()"
                        maxlength="8" show-word-limit class="limit" />
            </el-form-item>
          </el-col>
        </el-row>

        <!--        <el-row>-->
        <!--          <el-col :span="24">-->
        <!--            <el-form-item label="是否可见"  prop="visible">-->
        <!--              <el-switch-->
        <!--                v-model="visibleBoolean"-->
        <!--              />-->
        <!--              <el-tooltip class="item" effect="dark" content="选择不可见只注册路由不显示在侧边栏，比如添加页面应该选择不可见" placement="right-start">-->
        <!--                <i class="el-icon-question" />-->
        <!--              </el-tooltip>-->
        <!--            </el-form-item>-->
        <!--          </el-col>-->
        <!--        </el-row>-->
        <el-row>
          <el-col>
            <el-divider />
          </el-col>
        </el-row>

        <el-row>
          <el-col v-if="addMenuForm.menuType == 'C'" :span="24">
            <el-form-item prop="visible" label-width="108px">
              <span slot="label">
                <span class="span-box">
                  <el-tooltip class="item" effect="dark" content="选择隐藏则路由将不会出现在侧边栏，但仍然可以访问"
                              placement="top-start">
                    <i class="el-icon-question" />
                  </el-tooltip>
                  <span> 显示状态 </span>
                </span>
              </span>
              <el-radio v-model="addMenuForm.visible" :label="'Y'" @change="$forceUpdate()">显示</el-radio>
              <el-radio v-model="addMenuForm.visible" :label="'N'" @change="$forceUpdate()">隐藏</el-radio>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item v-if="addMenuForm.menuType === 'C'" prop="antdvLinkOpenType" label-width="108px">
              <span slot="label">
                <span class="span-box">
                  <el-tooltip class="item" effect="dark" content="请选择打开方式"
                              placement="top-start">
                    <i class="el-icon-question" />
                  </el-tooltip>
                  <span> 打开方式 </span>
                </span>
              </span>
              <el-radio v-model="addMenuForm.antdvLinkOpenType" :label="0">组件</el-radio>
              <el-radio v-model="addMenuForm.antdvLinkOpenType" :label="1">内部链接</el-radio>
              <el-radio v-model="addMenuForm.antdvLinkOpenType" :label="2">外部链接</el-radio>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col v-if="addMenuForm.menuType == 'C'" :span="24">
            <el-form-item prop="multiTab" label-width="108px">
              <span slot="label">
                <span class="span-box">
                  <el-tooltip class="item" effect="dark" content="多页签可创建多个不同数据的相同页签，"
                              placement="top-start">
                    <i class="el-icon-question" />
                  </el-tooltip>
                  <span> 多页签 </span>
                </span>
              </span>
              <el-radio v-model="addMenuForm.multiTab" :label="'Y'" @change="$forceUpdate()">是</el-radio>
              <el-radio v-model="addMenuForm.multiTab" :label="'N'" @change="$forceUpdate()">否</el-radio>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col v-if="addMenuForm.menuType == 'C'" :span="24">
            <el-form-item prop="fullScreen" label-width="108px">
              <span slot="label">
                <span class="span-box">
                  <el-tooltip class="item" effect="dark" content="全屏后将覆盖整个屏幕"
                              placement="top-start">
                    <i class="el-icon-question" />
                  </el-tooltip>
                  <span> 全屏 </span>
                </span>
              </span>
              <el-radio v-model="addMenuForm.fullScreen" :label="'Y'" @change="$forceUpdate()">是</el-radio>
              <el-radio v-model="addMenuForm.fullScreen" :label="'N'" @change="$forceUpdate()">否</el-radio>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item prop="antdvRouter" label-width="108px">
              <span slot="label">
                <span class="span-box">
                  <el-tooltip class="item" effect="dark" :content="`说明：${pathName}，${pathNameTips}`"
                              placement="top-start">
                    <i class="el-icon-question" />
                  </el-tooltip>
                  {{ pathName }}
                </span>
              </span>
              <el-input v-model.trim="addMenuForm.antdvRouter" style="width: 96%;" :placeholder="`请输入${pathName}`" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row v-if="addMenuForm.antdvLinkOpenType !== 2">
          <el-col :span="24">
            <el-form-item prop="antdvComponent" label-width="108px">
              <span slot="label">
                <span class="span-box">
                  <el-tooltip class="item" effect="dark" :content="`说明：${componentName}，${componentNameTips}`"
                              placement="top-start">
                    <i class="el-icon-question" />
                  </el-tooltip>
                  {{ componentName }}
                </span>
              </span>
              <el-input v-model.trim="addMenuForm.antdvComponent" :disabled="addMenuForm.menuType == 'M'?true:false" style="width: 96%;"
                        :placeholder="`请输入${componentName}`" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col>
            <el-divider />
          </el-col>
        </el-row>
      </el-form>
    </dtDialog>
  </div>
</template>
<script>
import IconPicker from './IconPicker/index'
import { getSysMenuTree, addSysMenu, getSysMenuDetail, editSysMenu, getSysAppList } from '@/framework/api/menu'
import { isExternal, positiveInteger } from '@/framework/utils/validate'
import { pick } from 'lodash'
import { upperCamelCase } from '@/framework/utils/index'

export default {
  name: 'MenuModal',
  components: {
    IconPicker
  },
  data() {
    return {
      loading: false,
      buttonLoading: false,
      action: '',
      dialogVisible: false,
      insideDialogVisible: false,
      antdvComponentEdit: '',
      filterText: '',
      addMenuForm: {
        menuName: '',
        menuCode: '',
        menuParentName: '',
        antdvRouter: '',
        antdvComponent: '',
        antdvIcon: '',
        menuSort: '',
        menuType: 'M',
        appCode: '',
        menuParentId: '',
        antdvLinkOpenType: 0,
        visible: 'Y',
        multiTab: 'N', // 是否多页签（Y-是 N-否）
        fullScreen: 'N' // 是否全屏：（Y-是 N-否）
      },
      visibleBoolean: true,
      menuTree: {
        ref: 'tree',
        props: {
          label: 'title',
          children: 'children'
        },
        data: [],
        defaultExpandedKeys: ['-1']
      },
      iconOption: {
        FontAwesome: false,
        ElementUI: true,
        eIcon: false,
        eIconSymbol: false,
        addIconList: [],
        removeIconList: []
      },
      rules: {
        name: [
          { required: true, message: '请输入活动名称', trigger: 'change' }
        ],
        menuName: [
          { required: true, message: '请输入菜单名称', trigger: 'change' }
        ],
        menuCode: [
          { required: true, message: '请输入菜单编号', trigger: 'change' }
        ],
        menuSort: [
          { required: true, message: '请输入排序', trigger: 'change' }
        ],
        menuType: [
          { required: true, message: '请选择菜单类型', trigger: 'change' }
        ],
        menuParentName: [
          { required: true, message: '请选择父级菜单', trigger: 'change' }
        ],
        antdvIcon: [{ required: true,
          message: '请选择图标',
          trigger: 'change',
          validator: (rule, value, callback) => {
            if (!this.addMenuForm.antdvIcon) {
              callback(new Error('请选择菜单图标'))
            } else callback()
          } }],
        appCode: [
          { required: true, message: '请选择所属应用', trigger: 'change' }
        ],
        antdvLinkOpenType: [
          { required: true, message: '请选择打开方式', trigger: 'change' }
        ],
        antdvRouter: [
          { required: true, validator: this.validateRouter, trigger: 'change' }
        ],
        antdvComponent: [
          { required: true, validator: this.validateComponent, trigger: 'change' }
        ]
      },
      sysAppList: []
    }
  },
  computed: {
    tenantId() {
      return this.$store.state.user.tenantId
    },
    modalTitle() {
      let title = ''
      if (this.action === 'add') {
        title = '新增菜单'
      } else if (this.action === 'edit') {
        title = '修改菜单'
      }
      return title
    },
    componentName() {
      let title = ''
      if (!this.addMenuForm.antdvLinkOpenType || this.addMenuForm.antdvLinkOpenType === 0) {
        title = '组件路径'
      } else if (this.addMenuForm.antdvLinkOpenType === 1) {
        title = '内链地址'
      }
      return title
    },
    componentNameTips() {
      return (!this.addMenuForm.antdvLinkOpenType || this.addMenuForm.antdvLinkOpenType === 0) ? '如：`system/user/index`，默认在`views/`目录下' : '链接地址以`http(s):// `开头'
    },
    pathName() {
      return (this.addMenuForm.menuType === 'M' || !this.addMenuForm.antdvLinkOpenType || this.addMenuForm.antdvLinkOpenType === 0 || this.addMenuForm.antdvLinkOpenType === 1) ? '路由地址' : '外链地址'
    },
    pathNameTips() {
      return (this.addMenuForm.menuType === 'M' || !this.addMenuForm.antdvLinkOpenType || this.addMenuForm.antdvLinkOpenType === 0 || this.addMenuForm.antdvLinkOpenType === 1) ? '如:`/user`' : '链接地址以`http(s):// `开头'
    }
  },

  watch: {
    // 切换菜单类型
    'addMenuForm.menuType': function (newValue, value) {
      if (newValue == 'M') this.addMenuForm.visible = 'Y'
    },
    'addMenuForm.antdvLinkOpenType': function (newValue, oldValue) {
      this.$refs.addMenuFormRef.clearValidate(['antdvRouter', 'antdvComponent'])
    },
    filterText(val) {
      // getSysMenuTree().then(resp => {
      //   this.menuTree.data = [...resp.data]
      // })
      this.$refs.tree.filter(val)
    }
  },
  created() {
    getSysAppList().then((resp) => {
      if (resp.success) {
        if (this.tenantId === '000000') {
          this.sysAppList = resp.data
        } else {
          this.sysAppList = resp.data.map((item) => {
            if (item.isDefault !== 2) {
              return item
            }
          }).filter((item) => { return item !== undefined })
        }
      }
    })
  },
  methods: {
    // 切换菜单类型
    handleMenuType(val) {
      this.addMenuForm.fullScreen = 'N'
      this.addMenuForm.multiTab = 'N'
      if (val === 'M') {
        this.addMenuForm.antdvLinkOpenType = 0
        // todo  如果是目录且父级菜单 是顶级菜单  antdvComponent 值为 layout
        // todo  如果是目录父级菜单 不是顶级菜单 antdvComponent 值为 framework/views/layouts/secondView
        if (this.addMenuForm.menuParentId != -1) {
          this.$set(this.addMenuForm, 'antdvComponent', 'framework/views/layouts/secondView')
        } else {
          this.$set(this.addMenuForm, 'antdvComponent', 'layout')
        }
      } else {
        this.addMenuForm.antdvLinkOpenType = 0
        this.addMenuForm.antdvComponent = this.antdvComponentEdit
        this.$set(this.addMenuForm, 'antdvComponent', this.antdvComponentEdit)
        this.$nextTick(() => {
          this.$refs.addMenuFormRef.clearValidate(['antdvComponent'])
        })
      }
    },
    // 校验排序规则
    initPositiveInteger(data) {
      return positiveInteger(data)
    },
    add() {
      this.edit({})
    },
    appCodeChange(item, index) {
      this.addMenuForm.menuParentName = ''
    },
    edit(record) {
      if (this.action !== 'add' && this.action !== '') {
        const params = {
          menuId: record.menuId
        }
        getSysMenuDetail(params).then((resp) => {
          this.addMenuForm = Object.assign({}, pick(resp.data,
            'menuId', 'menuName', 'menuCode', 'menuParentId', 'menuParentName', 'antdvRouter', 'antdvComponent', 'antdvIcon', 'menuSort', 'menuType', 'appCode', 'antdvLinkOpenType', 'multiTab', 'fullScreen'))
          this.addMenuForm.visible = resp.data.antdvVisible
          // if (resp.data.antdvVisible) {
          //   this.visibleBoolean = (resp.data.antdvVisible === 'Y')
          // }
          this.antdvComponentEdit = JSON.parse(JSON.stringify(this.addMenuForm.antdvComponent)) // 备份编辑进入时的组件路径
        })
      } else {
        this.antdvComponentEdit = ''
        this.handleMenuType('M')
      }
      this.dialogVisible = true
    },
    // 点击菜单路径
    onFocusMenuPath() {
      this.insideDialogVisible = true
      this.filterText = ''
      getSysMenuTree({ appCode: this.addMenuForm.appCode }).then((resp) => {
        this.menuTree.data = [...resp.data]
      })
    },
    // 点击保存父菜单
    onSaveParentMenu() {
      const treeNode = this.$refs.tree.getCurrentNode()
      if (treeNode != null) {
        this.addMenuForm.menuParentName = treeNode.title
        this.addMenuForm.menuParentId = treeNode.id
      }
      // this.addMenuForm.menuParentId = treeNode.id
      this.handleMenuType(this.addMenuForm.menuType)
      this.insideDialogVisible = false
    },
    filterNode(value, data) {
      if (!value) return true
      return data.title.indexOf(value) !== -1
    },
    // 点击提交
    onSubmit() {
      // 校验表单
      this.$refs.addMenuFormRef.validate((result, message) => {
        // 校验通过
        if (result) {
          this.loading = true
          if (this.buttonLoading) {
            return
          }
          // todo 初始化name
          this.addMenuForm.menuCode = upperCamelCase(this.addMenuForm.menuCode)
          if (this.action === 'add') {
            // 提交按钮显示加载中，无法重复点击
            this.buttonLoading = true

            // 发送请求，新增菜单
            addSysMenu(this.addMenuForm).then((resp) => {
              const type = resp.success ? 'success' : 'error'
              // 提示消息
              this.$message({
                type,
                message: '新增成功'
              })
              // 添加成功，自动关闭菜单添加对话框
              if (resp.success) {
                this.dialogVisible = false
                this.$emit('added')
              } else {
                this.buttonLoading = false
              }
              this.loading = false
            }).catch(() => {
              this.loading = false
              this.buttonLoading = false
            })
          } else if (this.action === 'edit') {
            this.buttonLoading = true
            editSysMenu(this.addMenuForm).then((resp) => {
              const type = resp.success ? 'success' : 'error'
              // 提示消息
              this.$message({
                type,
                message: '修改成功'
              })
              // 添加成功，自动关闭菜单添加对话框
              if (resp.success) {
                this.dialogVisible = false
                this.$emit('edited')
              } else {
                this.buttonLoading = false
              }
              this.loading = false
            }).catch(() => {
              this.loading = false
              // 启用提交按钮
              this.buttonLoading = false
            })
          }
        }
      })
    },
    initModal() {
      this.$refs.addMenuFormRef.resetFields()
      this.addMenuForm = {
        menuName: '',
        menuCode: '',
        menuParentName: '',
        layuiPath: '',
        antdvIcon: '',
        menuSort: '',
        menuType: 'M',
        appCode: '',
        menuParentId: '',
        antdvLinkOpenType: 0,
        visible: 'Y',
        multiTab: 'N', // 是否多页签（Y-是 N-否）
        fullScreen: 'N' // 是否全屏：（Y-是 N-否）
      }
    },
    onModalClosed() {
      this.initModal()
      this.buttonLoading = false
    },
    handleSelectedIcon(icon) {
      this.addMenuForm.antdvIcon = icon
      if (this.addMenuForm.appIcon) {
        this.$refs.addMenuFormRef.clearValidate('antdvIcon')
      } else {
        this.$refs.addMenuFormRef.validateField('antdvIcon')
      }
    },
    validateRouter(rule, value, callback) {
      if (this.addMenuForm.antdvLinkOpenType === 0 || this.addMenuForm.antdvLinkOpenType === 1) { // 组件，内链，路由地址必须以/开头
        if (!value) {
          callback(new Error('请输入路由地址'))
        } else if (!value.startsWith('/')) {
          callback(new Error('路由地址必须以 / 开头'))
        } else {
          callback()
        }
      } else if (this.addMenuForm.antdvLinkOpenType === 2) { // 外链，路由地址为外部地址
        if (!value) {
          callback(new Error('请输入外链地址'))
        } else if (!isExternal(value)) {
          callback(new Error('外链地址必须以 https:// 或者 http:// 开头'))
        } else {
          callback()
        }
      } else {
        callback()
      }
    },
    validateComponent(rule, value, callback) {
      if (this.addMenuForm.antdvLinkOpenType === 0) { // 组件，
        if (!value) {
          callback(new Error('请输入组件路径'))
        } else if (!(value.startsWith('views/') || value.startsWith('framework/'))) {
          if (this.addMenuForm.menuType == 'C') {
            callback(new Error('组件路径必须以 views/ 或是 framework/ 开头'))
          } else {
            callback()
          }
        } else {
          callback()
        }
      } else if (this.addMenuForm.antdvLinkOpenType === 1) { // 内链，组件地址就是内链地址
        if (!value) {
          callback(new Error('请输入内链地址'))
        } else if (!value.startsWith('/') && !isExternal(value)) {
          callback(new Error('内链地址必须以 https:// 或者 http:// 开头'))
        } else {
          callback()
        }
      } else if (this.addMenuForm.antdvLinkOpenType === 2) { // 外链，不需要组件地址
        callback()
      } else {
        callback()
      }
    }
  }
}
</script>

<style lang="scss">
  .add-menu-dialog .el-dialog__body {
    height: 500px;
    padding-top: 0;
    overflow-y: auto;
  }

  .add-menu-dialog .el-dialog {
    margin-top: 5vh !important;
  }
</style>
<style lang="scss" scoped>
  .item {
    margin: 4px;
  }

  .tips {
    padding-left: 50px ;
    color: red;

  }

  .icon_class {
    // color: red;
    ::v-deep .el-form-item__content {
      display: flex;

      .el-icon-delete {
        margin-left: 10px;
        line-height: 36px;
        cursor: pointer;
      }
    }
  }
</style>
